export const forEach = (arr, fn) => {
	if (!arr.length || !fn) return
	let i = -1
	let len = arr.length
	while (++i < len) {
		let item = arr[i]
		fn(item, i, arr)
	}
}

/**
 * @param {Array} target 目标数组
 * @param {Array} arr 需要查询的数组
 * @description 判断要查询的数组是否至少有一个元素包含在目标数组中
 */
export const hasOneOf = (target, arr) => {
	return target.some(_ => arr.indexOf(_) > -1)
}


/**
 * @param {Number} timeStamp 判断时间戳格式是否是毫秒
 * @returns {Boolean}
 */
const isMillisecond = timeStamp => {
	const timeStr = String(timeStamp)
	return timeStr.length > 10
}


/**
 * @param {Number} timeStamp 传入的时间戳
 * @param {Number} currentTime 当前时间时间戳
 * @returns {Boolean} 传入的时间戳是否早于当前时间戳
 */
const isEarly = (timeStamp, currentTime) => {
	return timeStamp < currentTime
}


/**
 * @param {Number} num 数值
 * @returns {String} 处理后的字符串
 * @description 如果传入的数值小于10，即位数只有1位，则在前面补充0
 */
const getHandledValue = num => {
	return num < 10 ? '0' + num : num
}

/**
 * @param {Number} timeStamp 传入的时间戳
 * @param {Number} startType 要返回的时间字符串的格式类型，传入'year'则返回年开头的完整时间
 */
const getDate = (timeStamp, startType) => {
	const d = new Date(timeStamp * 1000)
	const year = d.getFullYear()
	const month = getHandledValue(d.getMonth() + 1)
	const date = getHandledValue(d.getDate())
	const hours = getHandledValue(d.getHours())
	const minutes = getHandledValue(d.getMinutes())
	const second = getHandledValue(d.getSeconds())
	let resStr = ''
	if (startType === 'year') resStr = year + '-' + month + '-' + date + ' ' + hours + ':' + minutes + ':' + second
	else resStr = month + '-' + date + ' ' + hours + ':' + minutes
	return resStr
}
/**
 * @param {Number} timeStamp 传入的时间戳
 * @returns {String} 处理后的字符串 日期 
 */
export const getDateMD = (timeStamp) => {
	const date = new Date(timeStamp)
	const M = date.getMonth() + 1 + '月'
	const D = date.getDate() + '日'
	let resStr = M + D
	return resStr
}
/**
 * @param {Number} timeStamp 传入的时间戳
 * @returns {String} 处理后的字符串 小时 分钟 
 */
export const getDateHM = (timeStamp) => {
	const date = new Date(timeStamp)
	const H = date.getHours() + ':'
	const M = date.getMinutes()
	let m = M.toString()
	if (m.length === 1) {
		m = '0' + m
	}
	let resStr = H + m
	return resStr
}

/**
 * @param {String|Number} timeStamp 时间戳
 * @returns {String} 相对时间字符串
 */
export const getRelativeTime = timeStamp => {
	// 判断当前传入的时间戳是秒格式还是毫秒
	const IS_MILLISECOND = isMillisecond(timeStamp)
	// 如果是毫秒格式则转为秒格式
	if (IS_MILLISECOND) Math.floor(timeStamp /= 1000)
	// 传入的时间戳可以是数值或字符串类型，这里统一转为数值类型
	timeStamp = Number(timeStamp)
	// 获取当前时间时间戳
	const currentTime = Math.floor(Date.parse(new Date()) / 1000)
	// 判断传入时间戳是否早于当前时间戳
	const IS_EARLY = isEarly(timeStamp, currentTime)
	// 获取两个时间戳差值
	let diff = currentTime - timeStamp
	// 如果IS_EARLY为false则差值取反
	if (!IS_EARLY) diff = -diff
	let resStr = ''
	const dirStr = IS_EARLY ? '前' : '后'
	// 少于等于59秒
	if (diff <= 59) resStr = diff + '秒' + dirStr
	// 多于59秒，少于等于59分钟59秒
	else if (diff > 59 && diff <= 3599) resStr = Math.floor(diff / 60) + '分钟' + dirStr
	// 多于59分钟59秒，少于等于23小时59分钟59秒
	else if (diff > 3599 && diff <= 86399) resStr = Math.floor(diff / 3600) + '小时' + dirStr
	// 多于23小时59分钟59秒，少于等于29天59分钟59秒
	else if (diff > 86399 && diff <= 2623859) resStr = Math.floor(diff / 86400) + '天' + dirStr
	// 多于29天59分钟59秒，少于364天23小时59分钟59秒，且传入的时间戳早于当前
	else if (diff > 2623859 && diff <= 31567859 && IS_EARLY) resStr = getDate(timeStamp)
	else resStr = getDate(timeStamp, 'year')
	return resStr
}

/**
 * 处理时间格式
 * @parma fmt 规则
 * @parma date 时间
 * @returns {String} 时间字符串
 */
export const dateFtt = (fmt, date) => { //author: meizz 
	let o = {
		"M+": date.getMonth() + 1, //月份 
		"d+": date.getDate(), //日 
		"h+": date.getHours(), //小时 
		"m+": date.getMinutes(), //分 
		"s+": date.getSeconds(), //秒 
		"q+": Math.floor((date.getMonth() + 3) / 3), //季度 
		"S": date.getMilliseconds() //毫秒 
	};
	if (/(y+)/.test(fmt))
		fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
	for (var k in o)
		if (new RegExp("(" + k + ")").test(fmt))
			fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k])
				.length)));
	return fmt;
}




/* 
	倒计时
 */
export const countDown = endTime => {
	// 获取当前时间
	let date = new Date
	let now = date.getTime()
	// 截止时间
	let end = endTime.getTime()
	// 时间差
	let leftTime = end - now
	if (leftTime >= 0) {
		let d = Math.floor(leftTime / 1000 / 60 / 60 / 24)
		let h = Math.floor(leftTime / 1000 / 60 / 60 % 24)
		let m = Math.floor(leftTime / 1000 / 60 % 60)
		let s = Math.floor(leftTime / 1000 % 60);
	}
	console.log(d + '天' + h + '小时' + m + '分钟' + s + '秒')
}



/* 
 * @description 节流函数
 * @param {Fucntion} fn 延时调用函数
 * @param {Number} delay 延迟时间
 * @param {Number} atleast 至少多长时间触发一次
 * @return {Function} 延迟执行方法
 */
export const fnThrottle = (fn, delay, atleast) => {
	let timer = null
	let previous = null
	return function() {
		let now = +new Date()
		if (!previous) previous = now
		if (atleast && now - previous > atleast) {
			fn()
			previous = now
			clearTimeout(timer)
		} else {
			clearTimeout(timer)
			timer = setTimeout(function() {
				fn()
				previous = null
			}, delay)
		}
	}
}

/* 
 * @description 将数组按特定个数分割重组
 * @param ｛ Number ｝ num 每组个数
 * @param  { Array,Object } data 数组
 * @return { Array } 重组数组
 */
export const reslutArray = (data, num = 4) => {
	var result = [];
	for (var i = 0, len = data.length; i < len; i += num) {
		result.push(data.slice(i, i + num));
	}
	return result
}


/**
 * 解决两个数相加精度丢失问题
 * @param a
 * @param b
 * @returns {Number}
 */
export const floatAdd = (a, b) => {
	var c, d, e
	if (undefined === a || a === null || a === '' || isNaN(a)) {
		a = 0
	}
	if (undefined === b || b === null || b === '' || isNaN(b)) {
		b = 0
	}
	try {
		c = a.toString().split('.')[1].length
	} catch (f) {
		c = 0
	}
	try {
		d = b.toString().split('.')[1].length
	} catch (f) {
		d = 0
	}
	e = Math.pow(10, Math.max(c, d))
	return (floatMul(a, e) + floatMul(b, e)) / e
}
/**
 * 解决两个数相减精度丢失问题
 * @param a
 * @param b
 * @returns {Number}
 */
export const floatSub = (a, b) => {
	var c, d, e
	if (undefined === a || a === null || a === '' || isNaN(a)) {
		a = 0
	}
	if (undefined === b || b === null || b === '' || isNaN(b)) {
		b = 0
	}
	try {
		c = a.toString().split('.')[1].length
	} catch (f) {
		c = 0
	}
	try {
		d = b.toString().split('.')[1].length
	} catch (f) {
		d = 0
	}
	e = Math.pow(10, Math.max(c, d))
	return (floatMul(a, e) - floatMul(b, e)) / e
}
/**
 * 解决两个数相乘精度丢失问题
 * @param a
 * @param b
 * @returns {Number}
 */
export const floatMul = (a, b) => {
	var c = 0
	var d = a.toString()
	var e = b.toString()
	try {
		c += d.split('.')[1].length
	} catch (f) {}
	try {
		c += e.split('.')[1].length
	} catch (f) {}
	return Number(d.replace('.', '')) * Number(e.replace('.', '')) / Math.pow(10, c)
}
/**
 * 解决两个数相除精度丢失问题
 * @param a
 * @param b
 * @returns
 */
export const floatDiv = (a, b) => {
	var c;
	var d;
	var e = 0
	var f = 0
	try {
		e = a.toString().split('.')[1].length
	} catch (g) {}
	try {
		f = b.toString().split('.')[1].length
	} catch (g) {}
	// eslint-disable-next-line no-return-assign
	c = Number(a.toString().replace('.', ''))
	d = Number(b.toString().replace('.', ''))
	return floatMul(c / d, Math.pow(10, f - e))
}

/* 
	图片传base64
 */
export const image2Base64 = (img) => {
	var canvas = document.createElement('canvas')
	canvas.width = img.width
	canvas.height = img.height
	var ctx = canvas.getContext('2d')
	ctx.drawImage(img, 0, 0, img.width, img.height)
	var dataURL = canvas.toDataURL('image/png')
	return dataURL
}

export const getImgBase64 = (path) => {
	return new Promise((res, rej) => {
		var base64 = ''
		var img = new Image()
		img.src = path
		img.onload = function() {
			base64 = image2Base64(img)
			res(base64)
		}
		img.onerror = function(e) {
			rej(e)
		}
	})
}

// 判断是否为网络链接
export const isURl = (path) => {
	return (/^([hH][tT]{2}[pP]:\/\/|[hH][tT]{2}[pP][sS]:\/\/)(.)+$/.test(path))
}

export const deepClone = (obj) => {
	let objClone = Array.isArray(obj) ? [] : {};
	if (obj && typeof obj === 'object') {
		for (let key in obj) {
			if (obj[key] && typeof obj[key] === 'object') {
				objClone[key] = deepClone(obj[key]);
			} else {
				objClone[key] = obj[key]
			}
		}
	}
	return objClone;
}

function gDate(datestr){
  var temp = datestr.split("-");
  var date = new Date(temp[0],temp[1],temp[2]);
  return date;
}
export function getEveryDayDateByBetweenDate(start_date, end_date){
	var dateList = [start_date];
	if(start_date == end_date) return dateList;
	// dateList = []
	var startTime = gDate(start_date);
	var endTime = gDate(end_date);
	while((endTime.getTime()-startTime.getTime())>=0){
	  var year = startTime.getFullYear();
	  var month = startTime.getMonth().toString().length==1?"0"+startTime.getMonth().toString():startTime.getMonth();
	  var day = startTime.getDate().toString().length==1?"0"+startTime.getDate():startTime.getDate();
	  startTime.setDate(startTime.getDate()+1);
	  dateList.push(year+"-"+month+"-"+day)
	}
	return dateList;
}

export const  formatDate = (date)=> {
  const year = date.getFullYear(); // 获取年份
  const month = String(date.getMonth() + 1).padStart(2, '0'); // 获取月份并补零
  const day = String(date.getDate()).padStart(2, '0'); // 获取日期并补零
  return `${year}-${month}-${day}`;
}